﻿#include "EditorWidget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTextCursor>
#include <QTextCharFormat>
#include <QFontDatabase>
#include <QDebug>
#include <QLabel>
#include <QTextBlock>
#include <QMessageBox>
#include <QPainterPath>
#include <QPainter>

EditorWidget::EditorWidget(QWidget* parent) : QWidget(parent)
{
	m_printer.setPageSize(QPageSize(QPageSize::A4));
	m_pageSize = a4SizeToPixels();

	m_document = new QTextDocument(this);
	m_document->setPageSize(m_pageSize);

	QTextFrame* rootFrame = m_document->rootFrame();
	QTextFrameFormat frameFormat = rootFrame->frameFormat();
	frameFormat.setLeftMargin(50);   
	frameFormat.setTopMargin(50);
	frameFormat.setRightMargin(50);
	frameFormat.setBottomMargin(50);
	rootFrame->setFrameFormat(frameFormat);

	m_textEdit = new QTextEdit;
	m_textEdit->setDocument(m_document);
	m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
	m_textEdit->setAcceptRichText(true);
	m_textEdit->setUndoRedoEnabled(true);
	m_textEdit->setStyleSheet("background-color: transparent; border: none;");

	QFont font = m_textEdit->font();
	font.setPointSize(m_baseFontSize);
	m_textEdit->setFont(font);
	setupA4Canvas();

	connect(m_textEdit, &QTextEdit::cursorPositionChanged,this, &EditorWidget::onTextFormatChanged);
	connect(m_document, &QTextDocument::contentsChanged,this, &EditorWidget::updatePageLayout);
	connect(m_textEdit->document(), &QTextDocument::contentsChanged,this, &EditorWidget::onTextContentChanged);
	m_lastSavedTime = QDateTime::currentDateTime();
}

void EditorWidget::setModified(bool modified)
{
	if (m_isModified != modified) 
	{
		m_isModified = modified;
		emit modificationStateChanged(modified); 
	}
}

void EditorWidget::markAsSaved()
{
	setModified(false);
	m_lastSavedTime = QDateTime::currentDateTime(); 
}

void EditorWidget::setupA4Canvas()
{
	m_editorContainer = new QWidget;
	m_editorContainer->setStyleSheet("background-color: white;");

	QVBoxLayout* canvasLayout = new QVBoxLayout(m_editorContainer);
	canvasLayout->setContentsMargins(m_pageMargins.left(), m_pageMargins.top(),
		m_pageMargins.right(), m_pageMargins.bottom());
	canvasLayout->setAlignment(Qt::AlignCenter);       
	m_textEdit = new QTextEdit;
	m_textEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
	m_textEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 
	m_textEdit->setStyleSheet("background-color: transparent;");
	canvasLayout->addWidget(m_textEdit);

	m_scrollArea = new QScrollArea;
	m_scrollArea->setWidget(m_editorContainer);
	m_scrollArea->setStyleSheet("background-color: #f0f0f0;"); 
	m_scrollArea->setWidgetResizable(false);
	m_scrollArea->setAlignment(Qt::AlignCenter); 

	QVBoxLayout* mainLayout = new QVBoxLayout(this);
	mainLayout->setContentsMargins(0, 0, 0, 0);
	mainLayout->addWidget(m_scrollArea);

	updateZoom();
}

QSize EditorWidget::a4SizeToPixels() const
{
	QRectF pageRect = m_printer.pageRect(QPrinter::Point);
	int width = static_cast<int>(pageRect.width() * 96 / 72);
	int height = static_cast<int>(pageRect.height() * 96 / 72);
	return QSize(width, height);
}

void EditorWidget::setPageSizeA4()
{
	QSize a4Size = a4SizeToPixels();
	m_editorContainer->setFixedSize(a4Size);
	m_document->setPageSize(a4Size);
	updatePageLayout(); 
}

void EditorWidget::addPage()
{
	QTextCursor cursor = m_textEdit->textCursor();
	cursor.insertText("\f");
	cursor.movePosition(QTextCursor::NextCharacter);
	m_textEdit->setTextCursor(cursor);
}

void EditorWidget::zoomIn()
{
	if (m_zoomFactor < 3.0)
	{
		m_zoomFactor += 0.1;
		updateZoom();
	}
}

void EditorWidget::zoomOut()
{
	if (m_zoomFactor > 0.5)
	{
		m_zoomFactor -= 0.1;
		updateZoom();
	}
}

void EditorWidget::undo()
{
	if (m_textEdit->document()->isUndoAvailable()) 
		m_textEdit->undo();
}

void EditorWidget::redo()
{
	if (m_textEdit->document()->isRedoAvailable()) 
		m_textEdit->redo();

}

void EditorWidget::copy()
{
	m_textEdit->copy();
}

void EditorWidget::paste()
{
	m_textEdit->paste();
}


void EditorWidget::applyBold(bool bold)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontWeight(bold ? QFont::Bold : QFont::Normal);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);
	clearStyleMarker(); 
	onTextFormatChanged();
}

void EditorWidget::applyItalic(bool italic)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontItalic(italic);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);
	clearStyleMarker();
	onTextFormatChanged();
}

void EditorWidget::applyUnderline(bool underline)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontUnderline(underline);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);
	clearStyleMarker(); 
	onTextFormatChanged();
}

void EditorWidget::applyStrikethrough(bool strikethrough)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontStrikeOut(strikethrough); 
	cursor.setCharFormat(format);
	clearStyleMarker(); 
	onTextFormatChanged();
}

void EditorWidget::applyFontFamily(const QString& family)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontFamily(family);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);
	clearStyleMarker();
	onTextFormatChanged();
}

void EditorWidget::applyFontSize(int size)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontPointSize(size);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);

	QFont font = m_textEdit->font();
	font.setPointSize(size);
	m_textEdit->setFont(font);
	clearStyleMarker(); 
	onTextFormatChanged();
}

void EditorWidget::applyHeading1()
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setFontFamily("Arial");
	format.setFontPointSize(24);
	format.setFontWeight(QFont::Bold);
	format.setFontItalic(false);
	format.setFontUnderline(false);
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);

	onTextFormatChanged();
}

void EditorWidget::applyFontColor(const QColor& color)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	format.setForeground(QBrush(color));
	cursor.setCharFormat(format);
	m_textEdit->setTextCursor(cursor);
	clearStyleMarker();
	onTextFormatChanged();
}

void EditorWidget::applyHighlightColor(const QColor& color)
{
	QTextCursor cursor = m_textEdit->textCursor();
	bool hasSelection = cursor.hasSelection();

	QTextCharFormat format;
	format.setBackground(color); 

	if (hasSelection) 
		cursor.mergeCharFormat(format);
	else 
		m_textEdit->setCurrentCharFormat(format);
}

void EditorWidget::applyParagraphAlignment(Qt::Alignment alignment)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextBlockFormat format = cursor.blockFormat();
	if (alignment == (Qt::AlignJustify | Qt::AlignAbsolute))
	{
		format.setAlignment(Qt::AlignJustify);
		format.setProperty(QTextFormat::FontLetterSpacing, 1.2); 
	}
	else 
	{
		format.setAlignment(alignment);
		format.setProperty(QTextFormat::FontLetterSpacing, 1.0);
	}
	cursor.mergeBlockFormat(format);
	m_textEdit->setTextCursor(cursor);
	onTextFormatChanged();
}

QColor EditorWidget::currentHighlightColor() const
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();
	return format.background().color();
}

void EditorWidget::clearFormat()
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat fmt; 
	fmt.setFontFamily("Arial");
	fmt.setFontPointSize(12);
	fmt.setFontWeight(QFont::Normal);
	fmt.setFontItalic(false);
	fmt.setFontUnderline(false);
	fmt.setFontStrikeOut(false);
	fmt.setForeground(Qt::black);
	cursor.mergeCharFormat(fmt);
	QTextBlockFormat blockFmt;
	blockFmt.setAlignment(Qt::AlignLeft);
	cursor.mergeBlockFormat(blockFmt);
	onTextFormatChanged();
}

void EditorWidget::onTextFormatChanged()
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat format = cursor.charFormat();

	bool isBold = (format.fontWeight() == QFont::Bold);
	bool isItalic = format.fontItalic();
	bool isUnderline = format.fontUnderline();
	bool isStrikethrough = format.fontStrikeOut();
	QString fontFamily = format.fontFamily();
	int fontSize = static_cast<int>(format.fontPointSize());
	QColor fontColor = format.foreground().color();
	QColor highlightcolor = format.background().color();
	Qt::Alignment align = currentParagraphAlignment();
	if (fontSize <= 0) 
		fontSize = m_textEdit->font().pointSize(); 
	QString styleMarker = getSelectedStyleMarker();
	emit formatChanged(isBold, isItalic, isUnderline, isStrikethrough, fontFamily, fontSize, fontColor,highlightcolor, align, styleMarker);
}

void EditorWidget::updatePageLayout()
{
	int pageCount = m_document->pageCount();
	int totalHeight = m_pageSize.height() * pageCount;
	m_editorContainer->setFixedHeight(totalHeight);
	emit pageCountChanged(pageCount);
}

void EditorWidget::setPageMargins(int left, int top, int right, int bottom)
{
	m_pageMargins = QMargins(left, top, right, bottom);
	QTextFrame* rootFrame = m_document->rootFrame();
	QTextFrameFormat frameFormat = rootFrame->frameFormat();
	frameFormat.setLeftMargin(left);
	frameFormat.setTopMargin(top);
	frameFormat.setRightMargin(right);
	frameFormat.setBottomMargin(bottom);
	rootFrame->setFrameFormat(frameFormat);
	if (auto layout = qobject_cast<QVBoxLayout*>(m_editorContainer->layout())) 
		layout->setContentsMargins(left, top, right, bottom);
	updatePageLayout(); 
}

void EditorWidget::updateZoom()
{
	double hScrollRatio = 0.5;
	double vScrollRatio = 0.5;

	if (m_scrollArea->horizontalScrollBar()->maximum() > 0)
	{
		hScrollRatio = static_cast<double>(m_scrollArea->horizontalScrollBar()->value()) /
			m_scrollArea->horizontalScrollBar()->maximum();
	}

	if (m_scrollArea->verticalScrollBar()->maximum() > 0) 
	{
		vScrollRatio = static_cast<double>(m_scrollArea->verticalScrollBar()->value()) /
			m_scrollArea->verticalScrollBar()->maximum();
	}

	QSize originalSize = a4SizeToPixels();
	QSize scaledSize
	(
		static_cast<int>(originalSize.width() * m_zoomFactor),
		static_cast<int>(originalSize.height() * m_zoomFactor)
	);
	m_editorContainer->setFixedSize(scaledSize);
	QFont font = m_textEdit->font();
	font.setPointSizeF(12 * m_zoomFactor); 
	m_textEdit->setFont(font);

	if (m_scrollArea->horizontalScrollBar()->maximum() > 0) 
	{
		m_scrollArea->horizontalScrollBar()->setValue(
			hScrollRatio * m_scrollArea->horizontalScrollBar()->maximum());
	}

	if (m_scrollArea->verticalScrollBar()->maximum() > 0) 
	{
		m_scrollArea->verticalScrollBar()->setValue(
			vScrollRatio * m_scrollArea->verticalScrollBar()->maximum());
	}
}

int EditorWidget::pageCount() const
{
	return m_document->pageCount();
}

void EditorWidget::resetZoom()
{
	m_zoomFactor = 1.0;
	updateZoom();
}

qreal EditorWidget::currentZoom() const
{
	return m_zoomFactor;
}

void EditorWidget::cut()
{
	m_textEdit->cut();
}

bool EditorWidget::hasSelection() const
{
	return m_textEdit->textCursor().hasSelection();
}

void EditorWidget::setDocumentContent(const QString& html)
{
	m_textEdit->setHtml(html);
}

QString EditorWidget::getDocumentContent() const
{
	return m_textEdit->toHtml();
}

Qt::Alignment EditorWidget::currentParagraphAlignment() const
{
	QTextCursor cursor = m_textEdit->textCursor();
	if (cursor.block().isValid()) 
		return cursor.blockFormat().alignment();
	return Qt::AlignLeft; 
}

void EditorWidget::resetToDefaultStyle()
{
	QTextCursor cursor = m_textEdit->textCursor();
	cursor.select(QTextCursor::Document);
	QTextCharFormat fmt;
	fmt.setFontFamily("Arial");
	fmt.setFontPointSize(12);
	fmt.setFontWeight(QFont::Normal);
	fmt.setFontItalic(false);
	fmt.setFontUnderline(false);
	fmt.setFontStrikeOut(false);
	fmt.setForeground(Qt::black);
	cursor.mergeCharFormat(fmt);

	QTextBlockFormat blockFmt;
	blockFmt.setAlignment(Qt::AlignLeft);
	cursor.mergeBlockFormat(blockFmt);
	cursor.clearSelection();
	m_textEdit->setTextCursor(cursor);
	onTextFormatChanged();
}

void EditorWidget::setStyleMarker(const QString& styleName)
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat fmt = cursor.charFormat();
	fmt.setProperty(QTextFormat::UserProperty, styleName); 
	cursor.setCharFormat(fmt);
}

void EditorWidget::clearStyleMarker()
{
	QTextCursor cursor = m_textEdit->textCursor();
	QTextCharFormat fmt = cursor.charFormat();
	fmt.setProperty(QTextFormat::UserProperty, ""); 
	cursor.setCharFormat(fmt);
}

QString EditorWidget::getSelectedStyleMarker()
{
	QTextCursor cursor = m_textEdit->textCursor();
	if (!cursor.hasSelection()) return "";

	cursor.setPosition(cursor.selectionStart());
	QTextCharFormat fmt = cursor.charFormat();
	return fmt.property(QTextFormat::UserProperty).toString();
}

void EditorWidget::wheelEvent(QWheelEvent* event)
{
	if (event->modifiers() & Qt::ControlModifier) 
	{
		int delta = event->angleDelta().y();

		if (delta > 0) 
			zoomIn();
		else if (delta < 0) 
			zoomOut();
		event->accept();
	}
	else 
	{
		QWidget::wheelEvent(event);
	}
}

void EditorWidget::insertImage(const QString& imagePath)
{
	if (!QFile::exists(imagePath))
	{
		QMessageBox::warning(this, tr("错误"), tr("图片文件不存在：\n%1").arg(imagePath));
		return;
	}

	QImage image(imagePath);
	if (image.isNull())
	{
		QMessageBox::warning(this, tr("错误"), tr("无法加载图片：\n%1").arg(imagePath));
		return;
	}

	QTextCursor cursor = m_textEdit->textCursor();
	int maxWidth = m_pageSize.width() * 0.8; 
	QSize imageSize = image.size();

	if (imageSize.width() > maxWidth)
		imageSize.scale(maxWidth, imageSize.height(), Qt::KeepAspectRatio);

	QTextImageFormat imageFormat;
	imageFormat.setName(imagePath); 
	imageFormat.setWidth(imageSize.width()); 
	imageFormat.setHeight(imageSize.height());

	cursor.insertImage(imageFormat);
	m_textEdit->setTextCursor(cursor);
}

void EditorWidget::insertTable(int rows, int columns)
{
	if (rows <= 0 || columns <= 0) 
	{
		QMessageBox::warning(this, tr("错误"), tr("表格行数和列数必须为正数"));
		return;
	}
	QTextCursor cursor = m_textEdit->textCursor();
	QTextTableFormat tableFormat;
	tableFormat.setCellPadding(4);
	tableFormat.setCellSpacing(0);
	tableFormat.setBorder(1);
	tableFormat.setBorderStyle(QTextFrameFormat::BorderStyle_Solid); 

	int tableWidth = m_pageSize.width() * 0.8;
	tableFormat.setWidth(QTextLength(QTextLength::FixedLength, tableWidth));

	QTextTable* table = cursor.insertTable(rows, columns, tableFormat);
	if (table) 
	{
		cursor.movePosition(QTextCursor::NextCell);
		m_textEdit->setTextCursor(cursor);
	}
}
bool EditorWidget::isModified() const
{
	return m_isModified;
}

void EditorWidget::onTextChanged()
{
	setModified(true); 
	emit contentsChanged();
}

void EditorWidget::setPlainText(const QString& text)
{
	m_textEdit->setPlainText(text);
}

void EditorWidget::setHtml(const QString& html)
{
	m_textEdit->setHtml(html);
}

QDateTime EditorWidget::lastSavedTime() const
{
	return m_lastSavedTime;
}

void EditorWidget::onTextContentChanged()
{
	if (!m_isModified) 
	{
		setModified(true);
		emit contentsChanged();
	}
}

void EditorWidget::onShapeSelected(const QString& shapeType)
{
	m_currentShape = shapeType;
	setCursor(Qt::CrossCursor);
}

void EditorWidget::setCurrentShape(const QString& shapeType)
{
	m_currentShape = shapeType;
	if (!m_currentShape.isEmpty()) 
	{
		setCursor(Qt::CrossCursor); 
		m_isDrawing = false;
		qDebug() << "准备绘制形状:" << shapeType;
	}
}

void EditorWidget::mousePressEvent(QMouseEvent* event)
{
	if (event->button() == Qt::LeftButton && !m_currentShape.isEmpty()) 
	{
		m_startPos = event->pos();
		m_isDrawing = true;
		m_tempPath = QPainterPath(); 
		m_tempPath.moveTo(m_startPos);
		qDebug() << "绘制起点:" << m_startPos;
	}
	QWidget::mousePressEvent(event);
}

void EditorWidget::mouseReleaseEvent(QMouseEvent* event)
{
	if (event->button() == Qt::LeftButton && m_isDrawing) 
	{
		m_isDrawing = false;

		QPainterPath path;
		QPoint endPos = event->pos();

		if (m_currentShape == "rectangle") 
		{
			int x = qMin(m_startPos.x(), endPos.x());
			int y = qMin(m_startPos.y(), endPos.y());
			int width = qAbs(endPos.x() - m_startPos.x());
			int height = qAbs(endPos.y() - m_startPos.y());
			path.addRect(x, y, width, height);
		}
		else if (m_currentShape == "circle") 
		{
			int radius = qMin(
				qAbs(endPos.x() - m_startPos.x()),
				qAbs(endPos.y() - m_startPos.y())
			) / 2;
			QPoint center(
				(m_startPos.x() + endPos.x()) / 2,
				(m_startPos.y() + endPos.y()) / 2
			);
			path.addEllipse(center, radius, radius);
		}
		else if (m_currentShape == "line") 
		{
			path.moveTo(m_startPos);
			path.lineTo(endPos);
		}

		m_shapes.append(path);
		m_currentShape.clear(); 
		setCursor(Qt::ArrowCursor); 
		update(); 
		qDebug() << "形状绘制完成，已保存";
	}
	QWidget::mouseReleaseEvent(event);
}


void EditorWidget::paintEvent(QPaintEvent* event)
{
	Q_UNUSED(event);
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing); 

	painter.setPen(QPen(Qt::blue, 2));
	painter.setBrush(QBrush(QColor(200, 200, 255, 100))); 
	for (const auto& shape : m_shapes) 
	{
		painter.drawPath(shape);
	}

	if (m_isDrawing) 
	{
		painter.setPen(QPen(Qt::red, 2, Qt::DashLine));
		painter.setBrush(Qt::NoBrush);

		if (m_currentShape == "rectangle") 
		{
			int x = qMin(m_startPos.x(), QCursor::pos().x() - mapToGlobal(QPoint(0, 0)).x());
			int y = qMin(m_startPos.y(), QCursor::pos().y() - mapToGlobal(QPoint(0, 0)).y());
			int width = qAbs((QCursor::pos().x() - mapToGlobal(QPoint(0, 0)).x()) - m_startPos.x());
			int height = qAbs((QCursor::pos().y() - mapToGlobal(QPoint(0, 0)).y()) - m_startPos.y());
			painter.drawRect(x, y, width, height);
		}
		else if (m_currentShape == "circle") 
		{
			int radius = qMin(
				qAbs((QCursor::pos().x() - mapToGlobal(QPoint(0, 0)).x()) - m_startPos.x()),
				qAbs((QCursor::pos().y() - mapToGlobal(QPoint(0, 0)).y()) - m_startPos.y())
			) / 2;
			QPoint center(
				(m_startPos.x() + (QCursor::pos().x() - mapToGlobal(QPoint(0, 0)).x())) / 2,
				(m_startPos.y() + (QCursor::pos().y() - mapToGlobal(QPoint(0, 0)).y())) / 2
			);
			painter.drawEllipse(center, radius, radius);
		}
		else if (m_currentShape == "line") 
		{
			painter.drawLine(m_startPos, QCursor::pos() - mapToGlobal(QPoint(0, 0)));
		}
	}
}
